package com.doubao.wechat.service.impl;

import com.doubao.common.result.Result;
import com.doubao.common.utils.OrderNumberUtil;
import com.doubao.wechat.client.UserServiceClient;
import com.doubao.wechat.dto.response.MembershipLevelDTO;
import com.doubao.wechat.dto.response.UserInfoResponse;
import com.doubao.wechat.dto.request.WxPayOrderRequest;
import com.doubao.wechat.dto.response.WxPayOrderResponse;
import com.doubao.wechat.entity.PaymentOrder;
import com.doubao.wechat.mapper.PaymentOrderMapper;
import com.doubao.wechat.service.PaymentComposer;
import com.doubao.wechat.service.WxPayService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

/**
 * 支付流程编排器实现类
 * 负责协调整个支付流程，包括订单创建、支付、查询等
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class PaymentComposerImpl implements PaymentComposer {

    private final WxPayService wxPayService;
    private final PaymentOrderMapper paymentOrderMapper;

    @Autowired
    @Qualifier("com.doubao.wechat.client.UserServiceClient")
    private final UserServiceClient userServiceClient;

    @Value("${wechat.mp.appid}")
    private String mpAppId;

    @Value("${wechat.miniapp.appid}")
    private String miniappAppId;

    /**
     * 创建会员订单并发起支付
     */
    /**
     * 创建会员订单并发起支付 - 只支持月卡和年卡
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Map<String, Object>> createMembershipOrder(Long userId, Long membershipId,
                                                             Integer amount, String payType, String clientIp) {
        log.info("创建会员订单: userId={}, membershipId={}, amount={}, payType={}",
                userId, membershipId, amount, payType);

        try {
            // 1. 通过 UserFeignClient 获取用户的 OpenID
            Result<UserInfoResponse> userResult = userServiceClient.getUserInfo(userId);
            if (!userResult.isSuccess() || userResult.getData() == null) {
                log.error("获取用户信息失败: userId={}, error: {}", userId, userResult.getMessage());
                return Result.failed("获取用户信息失败: " + userResult.getMessage());
            }
            UserInfoResponse userInfo = userResult.getData();

            // 检查微信绑定状态
            if (Boolean.FALSE.equals(userInfo.getWechatBound())) {
                log.error("用户未绑定微信账号: userId={}", userId);
                return Result.failed("用户未绑定微信账号，无法支付");
            }

            // 2. 获取会员等级信息
            Result<MembershipLevelDTO> membershipResult = userServiceClient.getMembershipLevelInfo(membershipId);
            if (!membershipResult.isSuccess() || membershipResult.getData() == null) {
                log.error("获取会员等级信息失败: membershipId={}, error: {}", membershipId, membershipResult.getMessage());
                return Result.failed("获取会员等级信息失败: " + membershipResult.getMessage());
            }
            MembershipLevelDTO membershipInfo = membershipResult.getData();

            String openid = null;
            if ("jsapi".equalsIgnoreCase(payType)) {
                // 公众号支付
                openid = userInfo.getOfficialOpenid();
            } else {
                // 小程序支付
                openid = userInfo.getMiniappOpenid();
            }

            if (StringUtils.isBlank(openid)) {
                log.error("未获取到对应的微信OpenID: userId={}, payType={}", userId, payType);
                return Result.failed("未获取到对应的微信OpenID");
            }

            // 3. 生成商户订单号 - 会员订单前缀为VIP
            String outTradeNo = "VIP_" + OrderNumberUtil.generateOrderNumber();

            // 确定订阅类型 - 只支持月卡和年卡
            String subscriptionType;
            // 根据金额判断是月卡还是年卡
            int monthlyPrice = membershipInfo.getPriceMonthly() != null ? 
                    membershipInfo.getPriceMonthly().multiply(new BigDecimal(100)).intValue() : 0;
            int yearlyPrice = membershipInfo.getPriceYearly() != null ? 
                    membershipInfo.getPriceYearly().multiply(new BigDecimal(100)).intValue() : 0;
                    
            log.info("判断会员订阅类型 - 订单金额: {} 分, 月卡价格: {} 分, 年卡价格: {} 分", 
                    amount, monthlyPrice, yearlyPrice);
            
            // 增加金额匹配容错性，允许10%以内的误差
            if (Math.abs(amount - yearlyPrice) < yearlyPrice * 0.1 || amount == yearlyPrice) {
                subscriptionType = "YEARLY"; // 年卡
                log.info("识别为年卡订阅, 金额: {} 分, 年卡标准价格: {} 分", amount, yearlyPrice);
            } else if (Math.abs(amount - monthlyPrice) < monthlyPrice * 0.1 || amount == monthlyPrice) {
                subscriptionType = "MONTHLY"; // 月卡
                log.info("识别为月卡订阅, 金额: {} 分, 月卡标准价格: {} 分", amount, monthlyPrice);
            } else {
                subscriptionType = "MONTHLY"; // 默认月卡
                log.info("金额不匹配任何套餐价格(月卡:{} 分, 年卡:{} 分)，订单金额:{} 分，默认设置为月卡订阅", 
                        monthlyPrice, yearlyPrice, amount);
            }

            // 4. 创建本地支付订单记录
            PaymentOrder paymentOrder = new PaymentOrder();
            // 添加ID字段，解决 'id' cannot be null 错误
            paymentOrder.setId(outTradeNo); // 使用订单号作为ID
            paymentOrder.setUserId(userId);
            paymentOrder.setOutTradeNo(outTradeNo);
            paymentOrder.setProductId(membershipId);
            paymentOrder.setAmount(amount);

            // 使用从会员等级获取的信息充实订单信息
            String membershipTypeText = "YEARLY".equals(subscriptionType) ? "年卡" : "月卡";
            paymentOrder.setSubject(membershipInfo.getName() + membershipTypeText + "会员套餐"); // 添加会员等级和类型名称
            paymentOrder.setBody("购买" + membershipInfo.getName() + membershipTypeText + "会员服务: " + membershipInfo.getDescription()); // 添加会员等级描述
            paymentOrder.setPayChannel("wechat");
            paymentOrder.setPayType(payType);

            // 在附加信息中添加完整的会员详情
            String attachInfo = String.format("membershipOrder_%d_%s_name:%s_level:%s_tokens:%d_chats:%d",
                    membershipId,
                    subscriptionType,
                    membershipInfo.getName(),
                    membershipInfo.getCode(),
                    membershipInfo.getDailyTokenLimit(),
                    membershipInfo.getChatLimit());
            paymentOrder.setAttach(attachInfo);

            paymentOrder.setStatus("WAIT_PAY"); // 待支付
            paymentOrder.setCreatedAt(LocalDateTime.now());
            paymentOrder.setUpdatedAt(LocalDateTime.now());
            // 添加客户端IP，可能在某些支付场景中需要
            paymentOrder.setClientIp(clientIp);
            // 添加退款相关初始化字段
            paymentOrder.setRefundStatus(0);
            paymentOrder.setRefundAmount(0);
            // 设置过期时间
            paymentOrder.setExpireTime(LocalDateTime.now().plusHours(2));

            paymentOrderMapper.insert(paymentOrder);
            log.info("本地支付订单创建成功: {}", outTradeNo);

            // 5. 构建微信支付请求
            WxPayOrderRequest payRequest = new WxPayOrderRequest();
            payRequest.setOutTradeNo(outTradeNo);
            payRequest.setDescription(membershipInfo.getName() + membershipTypeText + "会员套餐");
            payRequest.setTotalAmount(amount);
            payRequest.setOpenid(openid);
            payRequest.setTradeType(payType.toUpperCase());
            payRequest.setAttach(attachInfo);
            payRequest.setUserId(userId);
            payRequest.setNotifyUrl(null);
            payRequest.setClientIp(clientIp);

            // 设置对应的APPID
            if ("jsapi".equalsIgnoreCase(payType)) {
                payRequest.setAppid(mpAppId);
            } else {
                payRequest.setAppid(miniappAppId);
            }

            // 6. 调用微信支付服务创建订单
            Result<WxPayOrderResponse> wxPayResult = wxPayService.createOrder(payRequest);
            if (!wxPayResult.isSuccess()) {
                log.error("微信支付下单失败: {}", wxPayResult.getMessage());
                return Result.failed("微信支付下单失败: " + wxPayResult.getMessage());
            }

            // 7. 构建返回数据
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("orderId", outTradeNo);
            resultMap.put("payInfo", wxPayResult.getData());
            resultMap.put("membershipInfo", membershipInfo); // 添加会员信息到返回结果

            log.info("会员订单创建成功: {}", outTradeNo);
            return Result.success(resultMap);

        } catch (Exception e) {
            log.error("创建会员订单异常", e);
            return Result.failed("创建会员订单异常: " + e.getMessage());
        }
    }

    /**
     * 查询订单并处理支付结果
     */
    @Override
    public Result<Map<String, Object>> queryAndProcessOrder(String outTradeNo) {
        log.info("查询订单: {}", outTradeNo);

        try {
            // 1. 查询本地订单
            PaymentOrder localOrder = paymentOrderMapper.selectByOutTradeNo(outTradeNo);
            if (localOrder == null) {
                log.error("本地订单不存在: {}", outTradeNo);
                return Result.failed("订单不存在");
            }

            // 2. 调用微信支付查询订单
            Result<Map<String, Object>> wxQueryResult = wxPayService.queryOrder(outTradeNo);
            if (!wxQueryResult.isSuccess()) {
                log.error("微信支付查询订单失败: {}", wxQueryResult.getMessage());

                // 如果是订单不存在错误，返回本地订单信息
                if (wxQueryResult.getMessage() != null && wxQueryResult.getMessage().contains("ORDER_NOT_EXIST")) {
                    Map<String, Object> resultMap = new HashMap<>();
                    resultMap.put("orderId", outTradeNo);
                    resultMap.put("status",
                            "WAIT_PAY".equals(localOrder.getStatus()) ? "WAIT_PAY" :
                                    "SUCCESS".equals(localOrder.getStatus()) ? "SUCCESS" : "PROCESSING");
                    resultMap.put("localOrder", localOrder);
                    return Result.success(resultMap);
                }

                return Result.failed(wxQueryResult.getMessage());
            }

            // 3. 获取微信支付订单信息
            Map<String, Object> wxOrderInfo = wxQueryResult.getData();

            // 4. 处理支付结果
            String tradeState = (String) wxOrderInfo.get("trade_state");
            log.info("订单 {} 的微信支付状态: {}", outTradeNo, tradeState);

            if ("SUCCESS".equals(tradeState)) {
                // 支付成功，更新本地订单状态
                if (!"SUCCESS".equals(localOrder.getStatus())) { // 如果不是已支付状态
                    String transactionId = (String) wxOrderInfo.get("transaction_id");
                    log.info("检测到订单 {} 支付成功，更新本地状态，微信交易号: {}", outTradeNo, transactionId);

                    // 更新订单状态
                    int rows = paymentOrderMapper.updatePaySuccess(outTradeNo, transactionId, "SUCCESS");
                    if (rows <= 0) {
                        log.error("更新订单状态失败: {}", outTradeNo);
                    } else {
                        log.info("成功更新订单状态为已支付: {}", outTradeNo);
                    }

                    // 处理支付成功回调，如果这是会员订单，则激活会员
                    if (outTradeNo.startsWith("VIP_")) {
                        log.info("开始处理会员订单激活: {}", outTradeNo);
                        Result<Void> callbackResult = handlePaymentCallback(outTradeNo, transactionId);
                        if (!callbackResult.isSuccess()) {
                            log.error("会员激活失败: {}, 原因: {}", outTradeNo, callbackResult.getMessage());
                        } else {
                            log.info("会员激活成功: {}", outTradeNo);
                        }
                    }
                } else {
                    log.info("订单 {} 已处于支付成功状态，无需更新", outTradeNo);
                }
            } else if ("CLOSED".equals(tradeState) || "REVOKED".equals(tradeState) || "PAYERROR".equals(tradeState)) {
                // 支付关闭/撤销/失败，更新本地订单状态
                if (!("CLOSED".equals(localOrder.getStatus()) || "REFUNDED".equals(localOrder.getStatus()))) { // 如果不是已关闭或失败状态
                    paymentOrderMapper.updateStatusByOutTradeNo(outTradeNo, "CLOSED"); // 支付失败
                    log.info("订单支付失败或关闭，已更新本地状态: {}, 状态: {}", outTradeNo, tradeState);
                }
            } else {
                log.info("订单 {} 的支付状态为: {}, 保持等待状态", outTradeNo, tradeState);
            }

            // 5. 构建返回数据
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("wxOrder", wxOrderInfo);
            resultMap.put("localOrder", paymentOrderMapper.selectByOutTradeNo(outTradeNo)); // 重新查询获取最新状态

            return Result.success(resultMap);

        } catch (Exception e) {
            log.error("查询订单异常", e);
            return Result.failed("查询订单异常: " + e.getMessage());
        }
    }

    /**
     * 处理支付成功回调 - 只支持月卡和年卡
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Void> handlePaymentCallback(String outTradeNo, String transactionId) {
        log.info("处理支付成功回调: outTradeNo={}, transactionId={}", outTradeNo, transactionId);

        try {
            // 1. 查询本地订单
            PaymentOrder order = paymentOrderMapper.selectByOutTradeNo(outTradeNo);
            if (order == null) {
                log.error("本地订单不存在: {}", outTradeNo);
                return Result.failed("订单不存在");
            }

            // 2. 检查订单状态，避免重复处理
            if ("SUCCESS".equals(order.getStatus())) {
                log.info("订单已处理，跳过: {}", outTradeNo);
                return Result.success();
            }

            // 3. 更新订单状态
            log.info("开始更新订单状态: outTradeNo={}, status=SUCCESS, transactionId={}", outTradeNo, transactionId);
            int rows = paymentOrderMapper.updatePaySuccess(outTradeNo, transactionId, "SUCCESS");
            if (rows <= 0) {
                log.error("更新订单状态失败: {}", outTradeNo);
                return Result.failed("更新订单状态失败");
            }
            log.info("订单状态已更新为已支付: {}", outTradeNo);

            // 4. 如果是会员订单，调用用户服务激活会员
            if (outTradeNo.startsWith("VIP_") && order.getAttach() != null && order.getAttach().startsWith("membershipOrder_")) {
                // 解析订单附加信息 - 支持新的附加信息格式
                String attach = order.getAttach();
                log.info("解析会员订单附加信息: {}", attach);

                String[] mainParts = attach.split("_", 4); // 分割主要部分，确保能够正确解析

                if (mainParts.length >= 3) {
                    Long membershipId;
                    String subscriptionType;

                    try {
                        membershipId = Long.parseLong(mainParts[1]);

                        // 提取订阅类型
                        if (mainParts.length > 2) {
                            if (mainParts[2].contains("_")) {
                                subscriptionType = mainParts[2].split("_")[0]; // 新格式: MONTHLY_name:xxx...
                            } else {
                                subscriptionType = mainParts[2]; // 旧格式: MONTHLY
                            }
                        } else {
                            subscriptionType = "MONTHLY"; // 默认月卡
                        }

                        // 简化订阅类型逻辑：如果不是年卡，一律视为月卡
                        if (!"YEARLY".equals(subscriptionType)) {
                            subscriptionType = "MONTHLY";
                        }

                        log.info("解析订阅信息成功: membershipId={}, subscriptionType={}", membershipId, subscriptionType);

                        // 根据订阅类型确定天数 - 只支持月卡和年卡
                        int days = "YEARLY".equals(subscriptionType) ? 365 : 30;

                        // 调用用户服务激活会员 - 使用重试机制确保调用成功
                        log.info("开始调用激活会员服务: userId={}, membershipId={}, type={}, days={}",
                                order.getUserId(), membershipId, subscriptionType, days);

                        Result<Void> activateResult = null;
                        int retryCount = 0;
                        int maxRetries = 3;
                        boolean success = false;

                        while (!success && retryCount < maxRetries) {
                            try {
                                log.info("尝试第 {} 次激活会员: userId={}, membershipId={}",
                                        retryCount + 1, order.getUserId(), membershipId);

                                activateResult = userServiceClient.activateMembership(
                                        order.getUserId(),
                                        membershipId.intValue(),
                                        subscriptionType,
                                        days,
                                        "payment",
                                        outTradeNo
                                );

                                // 详细记录调用结果
                                if (activateResult != null) {
                                    log.info("激活会员服务返回结果: success={}, message={}, data={}",
                                            activateResult.isSuccess(),
                                            activateResult.getMessage(),
                                            activateResult.getData());
                                } else {
                                    log.error("激活会员服务返回结果为空");
                                }

                                success = activateResult != null && activateResult.isSuccess();

                                if (success) {
                                    log.info("会员激活成功: userId={}, membershipId={}, subscriptionType={}, days={}",
                                            order.getUserId(), membershipId, subscriptionType, days);
                                } else {
                                    log.error("激活会员失败(尝试 {}/{}): userId={}, error={}",
                                            retryCount + 1, maxRetries, order.getUserId(),
                                            activateResult != null ? activateResult.getMessage() : "未知错误");
                                    Thread.sleep(1000); // 等待1秒后重试
                                }
                            } catch (Exception e) {
                                log.error("调用会员服务激活异常(尝试 {}/{}): userId={}, error={}",
                                        retryCount + 1, maxRetries, order.getUserId(), e.getMessage(), e);
                                Thread.sleep(1000); // 等待1秒后重试
                            }

                            retryCount++;
                        }

                        if (!success) {
                            // 所有重试都失败，记录错误并返回失败结果
                            log.error("激活会员失败(已重试{}次): userId={}, membershipId={}",
                                    maxRetries, order.getUserId(), membershipId);
                            return Result.failed("激活会员失败，请联系客服处理");
                        }

                    } catch (NumberFormatException e) {
                        log.error("解析会员ID失败: {}", mainParts[1], e);
                        return Result.failed("会员订单格式错误: " + e.getMessage());
                    } catch (Exception e) {
                        log.error("调用会员服务激活会员异常: userId={}", order.getUserId(), e);
                        return Result.failed("激活会员异常: " + e.getMessage());
                    }
                } else {
                    log.error("会员订单附加信息格式错误: {}", attach);
                    return Result.failed("会员订单附加信息格式错误");
                }
            } else {
                log.info("不是会员订单或格式不正确，跳过会员激活: {}, attach={}",
                        outTradeNo, order.getAttach());
            }

            return Result.success();

        } catch (Exception e) {
            log.error("处理支付回调异常", e);
            return Result.failed("处理支付回调异常: " + e.getMessage());
        }
    }

    /**
     * 取消支付订单
     * 
     * @param orderId 订单ID
     * @return 取消结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Map<String, Object>> cancelPayment(String orderId) {
        log.info("取消支付订单: {}", orderId);
        
        try {
            // 1. 查询本地订单
            PaymentOrder order = paymentOrderMapper.selectByOutTradeNo(orderId);
            if (order == null) {
                log.error("取消支付失败: 本地订单不存在, orderId={}", orderId);
                return Result.failed("订单不存在");
            }
            
            // 2. 检查订单状态，只有待支付的订单才能取消
            if (!"WAIT_PAY".equals(order.getStatus())) {
                log.error("取消支付失败: 订单状态不允许取消, orderId={}, status={}", orderId, order.getStatus());
                return Result.failed("订单状态不允许取消");
            }
            
            // 3. 调用微信支付关闭订单
            Result<Boolean> closeResult = wxPayService.closeOrder(orderId);
            if (!closeResult.isSuccess()) {
                log.error("调用微信支付关闭订单失败: {}", closeResult.getMessage());
                // 如果是订单不存在等非关键错误，仍然继续处理本地订单
                if (closeResult.getMessage() != null && 
                    (closeResult.getMessage().contains("ORDER_NOT_EXIST") || 
                     closeResult.getMessage().contains("ORDERCLOSED"))) {
                    log.info("微信支付订单已关闭或不存在，继续处理本地订单: {}", orderId);
                } else {
                    // 其他错误则返回失败
                    return Result.failed("关闭微信支付订单失败: " + closeResult.getMessage());
                }
            }
            
            // 4. 更新本地订单状态为已取消
            int rows = paymentOrderMapper.updateStatusByOutTradeNo(orderId, "CLOSED");
            if (rows <= 0) {
                log.error("更新订单状态失败: {}", orderId);
                return Result.failed("更新订单状态失败");
            }
            
            log.info("订单取消成功: {}", orderId);
            
            // 5. 构建返回数据
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("orderId", orderId);
            resultMap.put("status", "CLOSED");
            
            return Result.success(resultMap);
            
        } catch (Exception e) {
            log.error("取消支付异常", e);
            return Result.failed("取消支付异常: " + e.getMessage());
        }
    }
}